all files / fc-er/ Model.js

72.54% Statements 140/193
54% Branches 54/100
62.79% Functions 27/43
85.19% Lines 138/162
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353                         12280× 12280×   12275×     12280×     12280×       12280× 12280×   12280× 15×   15×                           12265× 12265×                     12272× 12272× 12275× 12275× 12275× 12273×     12275×       12272×     24558×     24556×     24552×     24548× 12276×     12272×             12276×         12276× 12276× 12276×     12276×             65488× 65488× 65488×   65488× 65486×           12326×   12326×   12326× 12326× 12326×   12326× 12284×     12326× 12326×                       12276×         12276× 12276× 12276× 12276×                     12286×         12290×   12290× 12290× 13× 13×     12290×         12294×   12294× 12294× 53199× 53198× 53198× 53197×         12294×     12294×                                                                                                         10833× 10833×       10833×     10833×                             12262×                        
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
 
function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }
 
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
 
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
 
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : _defaults(subClass, superClass); }
 
Iif (typeof define !== 'function') {
    var define = require('amdefine')(module);
}
 
define(function (require) {
    'use strict';
 
    var util = require('./util');
    var Deferred = require('./Deferred');
    var EventTarget = require('fc-mini-event/EventTarget');
 
    var SILENT = { silent: true };
 
    var loadData = function loadData(model, options) {
        var addDataToModel = function addDataToModel(value) {
            if (options.dump) {
                model.fill(value, SILENT);
            } else {
                model.set(options.name, value, SILENT);
            }
 
            return { success: true, name: options.name, options: options, value: value };
        };
 
        var buildError = function buildError(error) {
            return { success: false, name: options.name, options: options, error: error };
        };
 
        try {
            var value = options.retrieve(model, options);
 
            if (Deferred.isPromise(value)) {
                if (typeof value.abort === 'function') {
                    model.addPendingWorker(value);
                }
                return value.then(addDataToModel, function (error) {
                    error = buildError(error);
                    try {
                        var result = model.handleError(error);
                        return addDataToModel(result);
                    } catch (ex) {
                        if (ex.success === false) {
                            throw ex;
                        } else {
                            throw buildError(ex);
                        }
                    }
                });
            } else {
                var result = addDataToModel(value);
                return Promise.resolve(result);
            }
        } catch (ex) {
            var error = buildError(ex);
            return Promise.reject(error);
        }
    };
 
    var loadSequence = function loadSequence(model, datasource) {
        var loading = Promise.resolve();
        for (var i = 0; i < datasource.length; i++) {
            var unit = datasource[i];
            var task = util.bind(_load, null, model, unit);
            loading = loading.then(task);
        }
        return loading;
    };
 
    var loadParallel = function loadParallel(model, datasource) {
        var workers = [];
        for (var name in datasource) {
            Eif (datasource.hasOwnProperty(name)) {
                var unit = datasource[name];
                if (typeof unit === 'function') {
                    unit = { retrieve: unit, name: name };
                } else Eif (typeof unit.retrieve === 'function') {
                    unit = util.mix({ name: name }, unit);
                }
 
                workers.push(_load(model, unit));
            }
        }
 
        return Promise.all(workers);
    };
 
    var _load = function _load(model, datasource) {
        if (!datasource) {
            return Promise.resolve();
        }
 
        if (typeof datasource === 'function') {
            var options = { retrieve: datasource, dump: true };
            return loadData(model, options);
        }
 
        if (datasource instanceof Array) {
            return loadSequence(model, datasource);
        }
 
        if (typeof datasource.retrieve === 'function') {
            return loadData(model, datasource);
        }
 
        return loadParallel(model, datasource);
    };
 
    var removePendingWorker = function removePendingWorker(model, worker) {
        for (var i = 0; i < model.pendingWorkers.length; i++) {
            Eif (model.pendingWorkers[i] === worker) {
                model.pendingWorkers.splice(i, 1);
                return;
            }
        }
    };
 
    var forwardToPrepare = function forwardToPrepare() {
        var processError = function processError(ex) {
            var error = { success: false, name: '$prepare', options: {}, error: ex };
            throw error;
        };
 
        try {
            var preparing = this.prepare();
            Iif (Deferred.isPromise(preparing)) {
                return preparing.then(null, processError);
            } else {
                return preparing;
            }
        } catch (ex) {
            processError(ex);
        }
    };
 
    var setProperty = function setProperty(model, name, value) {
        var type = model.store.hasOwnProperty(name) ? 'change' : 'add';
        var oldValue = model.store[name];
        model.store[name] = value;
 
        if (oldValue !== value) {
            return { type: type, name: name, oldValue: oldValue, newValue: value };
        }
 
        return null;
    };
 
    var Model = function (_EventTarget) {
        _inherits(Model, _EventTarget);
 
        function Model(args) {
            _classCallCheck(this, Model);
 
            var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Model).call(this));
 
            _this.store = {};
            _this.pendingWorkers = [];
            _this.args = args;
 
            if (args) {
                _this.fill(args, SILENT);
            }
 
            _this.initialize();
            return _this;
        }
 
        _createClass(Model, [{
            key: 'initialize',
            value: function initialize() {}
        }, {
            key: 'addPendingWorker',
            value: function addPendingWorker(worker) {
                this.pendingWorkers.push(worker);
                var cbk = util.bind(removePendingWorker, null, this, worker);
                worker.then(cbk, cbk);
            }
        }, {
            key: 'getDatasource',
            value: function getDatasource() {
                return this.datasource;
            }
        }, {
            key: 'load',
            value: function load() {
                try {
                    var datasource = this.getDatasource();
                    var loading = _load(this, datasource);
                    return loading.then(util.bind(forwardToPrepare, this));
                } catch (ex) {
                    return Promise.reject(ex);
                }
            }
        }, {
            key: 'prepare',
            value: function prepare() {}
        }, {
            key: 'get',
            value: function get(name) {
                return this.store[name];
            }
        }, {
            key: 'set',
            value: function set(name, value, options) {
                options = options || {};
 
                var record = setProperty(this, name, value);
                if (record && !options.silent) {
                    var event = { changes: [record] };
                    this.fire('change', event);
                }
 
                return value;
            }
        }, {
            key: 'fill',
            value: function fill(extension, options) {
                options = options || {};
 
                var changes = [];
                for (var name in extension) {
                    if (extension.hasOwnProperty(name)) {
                        var record = setProperty(this, name, extension[name]);
                        if (record) {
                            changes.push(record);
                        }
                    }
                }
 
                if (changes.length && !options.silent) {
                    var event = { changes: changes };
                    this.fire('change', event);
                }
 
                return extension;
            }
        }, {
            key: 'remove',
            value: function remove(name, options) {
                if (!this.store.hasOwnProperty(name)) {
                    return;
                }
 
                options = options || {};
                var value = this.store[name];
                delete this.store[name];
 
                if (!options.silent) {
                    var event = { changes: [{ type: 'remove', name: name, oldValue: value, newValue: undefined }] };
                    this.fire('change', event);
                }
 
                return value;
            }
        }, {
            key: 'getAsModel',
            value: function getAsModel(name) {
                var value = this.get(name);
                Iif (!value || {}.toString.call(value) !== '[object Object]') {
                    return new Model();
                } else {
                    return new Model(value);
                }
            }
        }, {
            key: 'dump',
            value: function dump() {
                return util.mix({}, this.store);
            }
        }, {
            key: 'has',
            value: function has(name) {
                return this.store.hasOwnProperty(name);
            }
        }, {
            key: 'hasValue',
            value: function hasValue(name) {
                return this.has(name) && this.store[name] != null;
            }
        }, {
            key: 'hasReadableValue',
            value: function hasReadableValue(name) {
                return this.hasValue(name) && this.store[name] !== '';
            }
        }, {
            key: 'valueOf',
            value: function valueOf() {
                return this.dump();
            }
        }, {
            key: 'clone',
            value: function clone() {
                return new Model(this.store);
            }
        }, {
            key: 'handleError',
            value: function handleError(error) {
                throw error;
            }
        }, {
            key: 'dispose',
            value: function dispose() {
                Eif (this.pendingWorkers) {
                    for (var i = 0; i < this.pendingWorkers.length; i++) {
                        var worker = this.pendingWorkers[i];
                        Eif (typeof worker.abort === 'function') {
                            try {
                                worker.abort();
                            } catch (ex) {}
                        }
                    }
                    this.pendingWorkers = null;
                }
 
                this.destroyEvents();
            }
        }, {
            key: 'dehydrate',
            value: function dehydrate() {
                return this.dump();
            }
        }, {
            key: 'rehydrate',
            value: function rehydrate(rehydratedState) {
                this.fill(rehydratedState);
            }
        }, {
            key: 'setContext',
            value: function setContext(context) {
                this.context = context;
            }
        }, {
            key: 'getContext',
            value: function getContext() {
                return this.context;
            }
        }]);
 
        return Model;
    }(EventTarget);
 
    return Model;
});
//# sourceMappingURL=data:application/json;base64,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SyxPQUFMLENBREU7Ozs7O01BbEtHLGFBcEpFOztBQTRUdEIsV0FBTyxLQUFQLENBNVRzQjtDQUFuQixDQUFQIiwiZmlsZSI6Ik1vZGVsLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaWYgKHR5cGVvZiBkZWZpbmUgIT09ICdmdW5jdGlvbicpIHt2YXIgZGVmaW5lID0gcmVxdWlyZSgnYW1kZWZpbmUnKShtb2R1bGUpfVxuXG5kZWZpbmUoZnVuY3Rpb24gKHJlcXVpcmUpIHtcbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICBjb25zdCB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7XG4gICAgY29uc3QgRGVmZXJyZWQgPSByZXF1aXJlKCcuL0RlZmVycmVkJyk7XG4gICAgY29uc3QgRXZlbnRUYXJnZXQgPSByZXF1aXJlKCdmYy1taW5pLWV2ZW50L0V2ZW50VGFyZ2V0Jyk7XG5cbiAgICBjb25zdCBTSUxFTlQgPSB7c2lsZW50OiB0cnVlfTtcblxuICAgIGNvbnN0IGxvYWREYXRhID0gKG1vZGVsLCBvcHRpb25zKSA9PiB7XG4gICAgICAgIGNvbnN0IGFkZERhdGFUb01vZGVsID0gKHZhbHVlKSA9PiB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5kdW1wKSB7XG4gICAgICAgICAgICAgICAgbW9kZWwuZmlsbCh2YWx1ZSwgU0lMRU5UKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vZGVsLnNldChvcHRpb25zLm5hbWUsIHZhbHVlLCBTSUxFTlQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4ge3N1Y2Nlc3M6IHRydWUsIG5hbWU6IG9wdGlvbnMubmFtZSwgb3B0aW9ucywgdmFsdWV9O1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGJ1aWxkRXJyb3IgPSAoZXJyb3IpID0+ICh7c3VjY2VzczogZmFsc2UsIG5hbWU6IG9wdGlvbnMubmFtZSwgb3B0aW9ucywgZXJyb3J9KTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBvcHRpb25zLnJldHJpZXZlKG1vZGVsLCBvcHRpb25zKTtcblxuICAgICAgICAgICAgaWYgKERlZmVycmVkLmlzUHJvbWlzZSh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlLmFib3J0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZGVsLmFkZFBlbmRpbmdXb3JrZXIodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUudGhlbihhZGREYXRhVG9Nb2RlbCwgKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yID0gYnVpbGRFcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBtb2RlbC5oYW5kbGVFcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYWRkRGF0YVRvTW9kZWwocmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjYXRjaCAoZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChleC5zdWNjZXNzID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgYnVpbGRFcnJvcihleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGFkZERhdGFUb01vZGVsKHZhbHVlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IGJ1aWxkRXJyb3IoZXgpO1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdCBsb2FkU2VxdWVuY2UgPSAobW9kZWwsIGRhdGFzb3VyY2UpID0+IHtcbiAgICAgICAgbGV0IGxvYWRpbmcgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhc291cmNlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCB1bml0ID0gZGF0YXNvdXJjZVtpXTtcbiAgICAgICAgICAgIGNvbnN0IHRhc2sgPSB1dGlsLmJpbmQobG9hZCwgbnVsbCwgbW9kZWwsIHVuaXQpO1xuICAgICAgICAgICAgbG9hZGluZyA9IGxvYWRpbmcudGhlbih0YXNrKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbG9hZGluZztcbiAgICB9O1xuXG4gICAgY29uc3QgbG9hZFBhcmFsbGVsID0gKG1vZGVsLCBkYXRhc291cmNlKSA9PiB7XG4gICAgICAgIGNvbnN0IHdvcmtlcnMgPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCBuYW1lIGluIGRhdGFzb3VyY2UpIHtcbiAgICAgICAgICAgIGlmIChkYXRhc291cmNlLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICAgICAgICAgICAgbGV0IHVuaXQgPSBkYXRhc291cmNlW25hbWVdO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdW5pdCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICB1bml0ID0ge3JldHJpZXZlOiB1bml0LCBuYW1lfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIHVuaXQucmV0cmlldmUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgdW5pdCA9IHV0aWwubWl4KHtuYW1lfSwgdW5pdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgd29ya2Vycy5wdXNoKGxvYWQobW9kZWwsIHVuaXQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbCh3b3JrZXJzKTtcbiAgICB9O1xuXG4gICAgY29uc3QgbG9hZCA9IChtb2RlbCwgZGF0YXNvdXJjZSkgPT4ge1xuICAgICAgICBpZiAoIWRhdGFzb3VyY2UpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgZGF0YXNvdXJjZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtyZXRyaWV2ZTogZGF0YXNvdXJjZSwgZHVtcDogdHJ1ZX07XG4gICAgICAgICAgICByZXR1cm4gbG9hZERhdGEobW9kZWwsIG9wdGlvbnMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRhdGFzb3VyY2UgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgcmV0dXJuIGxvYWRTZXF1ZW5jZShtb2RlbCwgZGF0YXNvdXJjZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGRhdGFzb3VyY2UucmV0cmlldmUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiBsb2FkRGF0YShtb2RlbCwgZGF0YXNvdXJjZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbG9hZFBhcmFsbGVsKG1vZGVsLCBkYXRhc291cmNlKTtcbiAgICB9O1xuXG4gICAgY29uc3QgcmVtb3ZlUGVuZGluZ1dvcmtlciA9IChtb2RlbCwgd29ya2VyKSA9PiB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbW9kZWwucGVuZGluZ1dvcmtlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChtb2RlbC5wZW5kaW5nV29ya2Vyc1tpXSA9PT0gd29ya2VyKSB7XG4gICAgICAgICAgICAgICAgbW9kZWwucGVuZGluZ1dvcmtlcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjb25zdCBmb3J3YXJkVG9QcmVwYXJlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBwcm9jZXNzRXJyb3IgPSAoZXgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGVycm9yID0ge3N1Y2Nlc3M6IGZhbHNlLCBuYW1lOiAnJHByZXBhcmUnLCBvcHRpb25zOiB7fSwgZXJyb3I6IGV4fTtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9O1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBwcmVwYXJpbmcgPSB0aGlzLnByZXBhcmUoKTtcbiAgICAgICAgICAgIGlmIChEZWZlcnJlZC5pc1Byb21pc2UocHJlcGFyaW5nKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwcmVwYXJpbmcudGhlbihudWxsLCBwcm9jZXNzRXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByZXBhcmluZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXgpIHtcbiAgICAgICAgICAgIHByb2Nlc3NFcnJvcihleCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3Qgc2V0UHJvcGVydHkgPSAobW9kZWwsIG5hbWUsIHZhbHVlKSA9PiB7XG4gICAgICAgIGNvbnN0IHR5cGUgPSBtb2RlbC5zdG9yZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSA/ICdjaGFuZ2UnIDogJ2FkZCc7XG4gICAgICAgIGNvbnN0IG9sZFZhbHVlID0gbW9kZWwuc3RvcmVbbmFtZV07XG4gICAgICAgIG1vZGVsLnN0b3JlW25hbWVdID0gdmFsdWU7XG5cbiAgICAgICAgaWYgKG9sZFZhbHVlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHt0eXBlLCBuYW1lLCBvbGRWYWx1ZSwgbmV3VmFsdWU6IHZhbHVlfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG5cbiAgICBjbGFzcyBNb2RlbCBleHRlbmRzIEV2ZW50VGFyZ2V0IHtcbiAgICAgICAgY29uc3RydWN0b3IoYXJncykge1xuICAgICAgICAgICAgc3VwZXIoKTtcblxuICAgICAgICAgICAgdGhpcy5zdG9yZSA9IHt9O1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nV29ya2VycyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5hcmdzID0gYXJncztcblxuICAgICAgICAgICAgaWYgKGFyZ3MpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpbGwoYXJncywgU0lMRU5UKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpbml0aWFsaXplKCkge31cblxuICAgICAgICBhZGRQZW5kaW5nV29ya2VyKHdvcmtlcikge1xuICAgICAgICAgICAgdGhpcy5wZW5kaW5nV29ya2Vycy5wdXNoKHdvcmtlcik7XG4gICAgICAgICAgICBjb25zdCBjYmsgPSB1dGlsLmJpbmQocmVtb3ZlUGVuZGluZ1dvcmtlciwgbnVsbCwgdGhpcywgd29ya2VyKTtcbiAgICAgICAgICAgIHdvcmtlci50aGVuKGNiaywgY2JrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGdldERhdGFzb3VyY2UoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRhc291cmNlO1xuICAgICAgICB9XG5cbiAgICAgICAgbG9hZCgpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0YXNvdXJjZSA9IHRoaXMuZ2V0RGF0YXNvdXJjZSgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGxvYWRpbmcgPSBsb2FkKHRoaXMsIGRhdGFzb3VyY2UpO1xuICAgICAgICAgICAgICAgIHJldHVybiBsb2FkaW5nLnRoZW4odXRpbC5iaW5kKGZvcndhcmRUb1ByZXBhcmUsIHRoaXMpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChleCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBwcmVwYXJlKCkge31cblxuICAgICAgICBnZXQobmFtZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmVbbmFtZV07XG4gICAgICAgIH1cblxuICAgICAgICBzZXQobmFtZSwgdmFsdWUsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gICAgICAgICAgICBjb25zdCByZWNvcmQgPSBzZXRQcm9wZXJ0eSh0aGlzLCBuYW1lLCB2YWx1ZSk7XG4gICAgICAgICAgICBpZiAocmVjb3JkICYmICFvcHRpb25zLnNpbGVudCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50ID0ge2NoYW5nZXM6IFtyZWNvcmRdfTtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ2NoYW5nZScsIGV2ZW50KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgZmlsbChleHRlbnNpb24sIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gICAgICAgICAgICBjb25zdCBjaGFuZ2VzID0gW107XG4gICAgICAgICAgICBmb3IgKGNvbnN0IG5hbWUgaW4gZXh0ZW5zaW9uKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV4dGVuc2lvbi5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWNvcmQgPSBzZXRQcm9wZXJ0eSh0aGlzLCBuYW1lLCBleHRlbnNpb25bbmFtZV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVjb3JkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGFuZ2VzLnB1c2gocmVjb3JkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNoYW5nZXMubGVuZ3RoICYmICFvcHRpb25zLnNpbGVudCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50ID0ge2NoYW5nZXN9O1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZSgnY2hhbmdlJywgZXZlbnQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gZXh0ZW5zaW9uO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVtb3ZlKG5hbWUsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5zdG9yZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHRoaXMuc3RvcmVbbmFtZV07XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5zdG9yZVtuYW1lXTtcblxuICAgICAgICAgICAgaWYgKCFvcHRpb25zLnNpbGVudCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50ID0ge2NoYW5nZXM6IFt7dHlwZTogJ3JlbW92ZScsIG5hbWUsIG9sZFZhbHVlOiB2YWx1ZSwgbmV3VmFsdWU6IHVuZGVmaW5lZH1dfTtcbiAgICAgICAgICAgICAgICB0aGlzLmZpcmUoJ2NoYW5nZScsIGV2ZW50KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2V0QXNNb2RlbChuYW1lKSB7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHRoaXMuZ2V0KG5hbWUpO1xuICAgICAgICAgICAgaWYgKCF2YWx1ZSB8fCB7fS50b1N0cmluZy5jYWxsKHZhbHVlKSAhPT0gJ1tvYmplY3QgT2JqZWN0XScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IE1vZGVsKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IE1vZGVsKHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGR1bXAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdXRpbC5taXgoe30sIHRoaXMuc3RvcmUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaGFzKG5hbWUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0b3JlLmhhc093blByb3BlcnR5KG5hbWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaGFzVmFsdWUobmFtZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGFzKG5hbWUpICYmIHRoaXMuc3RvcmVbbmFtZV0gIT0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGhhc1JlYWRhYmxlVmFsdWUobmFtZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGFzVmFsdWUobmFtZSkgJiYgdGhpcy5zdG9yZVtuYW1lXSAhPT0gJyc7XG4gICAgICAgIH1cblxuICAgICAgICB2YWx1ZU9mKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZHVtcCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgY2xvbmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IE1vZGVsKHRoaXMuc3RvcmUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaGFuZGxlRXJyb3IoZXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG5cbiAgICAgICAgZGlzcG9zZSgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnBlbmRpbmdXb3JrZXJzKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnBlbmRpbmdXb3JrZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHdvcmtlciA9IHRoaXMucGVuZGluZ1dvcmtlcnNbaV07XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygd29ya2VyLmFib3J0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtlci5hYm9ydCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5wZW5kaW5nV29ya2VycyA9IG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZGVzdHJveUV2ZW50cygpO1xuICAgICAgICB9XG5cbiAgICAgICAgZGVoeWRyYXRlKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZHVtcCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVoeWRyYXRlKHJlaHlkcmF0ZWRTdGF0ZSkge1xuICAgICAgICAgICAgdGhpcy5maWxsKHJlaHlkcmF0ZWRTdGF0ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBzZXRDb250ZXh0KGNvbnRleHQpIHtcbiAgICAgICAgICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQ7XG4gICAgICAgIH1cblxuICAgICAgICBnZXRDb250ZXh0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udGV4dDtcbiAgICAgICAgfVxuXG4gICAgfVxuXG4gICAgcmV0dXJuIE1vZGVsO1xufSk7XG4iXX0=